PSR-7: HTTP Message Interfaces
本文
定義されているinterfaceは以下の7種類。ネストされたものは継承関係にある。
Psr\Http\Message\MessageInterface
Psr\Http\Message\RequestInterface
Psr\Http\Message\ServerRequestInterface
Psr\Http\Message\ResponseInterface
Psr\Http\Message\StreamInterface
Psr\Http\Message\UriInterface
Psr\Http\Message\UploadedFileInterface
MessageInterfaceはHTTPリクエストとHTTPレスポンスの共通要素を抽象化したもので、ヘッダフィールドやボディなどリクエストとレスポンスの両方に存在するメソッドを持っている。この継承構造におけるひとつの発見は、「クライアントが送るリクエストオブジェクト(RequestInterface)よりもサーバが受け取って処理するリクエストオブジェクト(ServerRequestInterface)の方が情報量が多い」ということである。その理由はMeta Documentに「Rationale for ServerRequestInterface」として記載されている。 また、HTTPメッセージ本体以外の関連する要素としてStreamInterface、UriInterface、UploadedFileInterfaceという値オブジェクトのインターフェイスが定義されている。重要なのはHTTPメッセージのボディを表現するために、PHPのストリームでラップすることを想定したStreamInterfaceを提供していることだろう。 fig/http-message-utilではHTTPメソッドの定数を持つFig\Http\Message\RequestMethodInterfaceと、ステータスコードの定数を持つFig\Http\Message\StatusCodeInterfaceという二つのインターフェイスを提供している。
このインターフェイスに依存することは必須ではないが、これらの定数をうまく利用することで、コード中の'GET'や200のようなマジックナンバーを避けることができる。どちらもメソッドの宣言を持っているわけではないが、実装クラスのimplementsに追加することでself::STATUS_OKのようなショートコーディングできることを意図している。
もちろんクラス組み込まずとも、以下のように使うこともできる。
code:php
<?php
use Fig\Http\Message\StatusCodeInterface as StatusCode;
class ResponseFactory implements StatusCodeInterface
{
public function createResponse($code = StatusCode::STATUS_OK)
{
self::STATUS_OKがいいか、StatusCode::STATUS_OKと書くのがいいかというのは好みの問題に属するだろう。
PSR-7はインターフェイスの定義なので、実装クラスがなければ利用できない。自作しても良いが、既存のものをどれか選ぶのが良いだろう。単体ライブラリとして導入するならPSR-17: HTTP Factoriesとセットになっているものから選択するのが良い。 2020年現在で最速を名乗るPSR-7/PSR-17実装クラス
PSR-17も実装されている
CakePHP(4.0.3)はこれを使っている
以前はZend Diactorosという名前だった
HTTPクライアントライブラリのGuzzleを入れるとついてくるPSR-7実装クラス PSR-17も実装されている
Packagistのパッケージ名はguzzlehttp/psr7なので注意
古いバージョンのguzzlehttp/psr7のフォーク版
PHP 5.3のサポートを継続している
“currently mising ServerRequestInterface and UploadedFileInterface” と宣言されており、PSR-15と併せて使えない
出力(emit)
PSR-7オブジェクトをPHPのレスポンスとして実際に出力することをemitと言う。簡単なのでライブラリを使わずに自作しても良いのだけれど、特に理由がなければ利用すべきだろう。
元zendframework/zend-httphandlerrunner
ど定番の鉄板
nyholm/psr7もguzzle/psr7もドキュメントでこれを紹介してるし、CakePHPも依存してる
シンプルな関数だけが欲しい場合はこっちでもいい
が、あまり使われてないのでlaminas-httphandlerrunnerの方がいいと思う
基本はこれだけ
code:php
<?php
$psr17Factory = new \Nyholm\Psr7\Factory\Psr17Factory();
$responseBody = $psr17Factory->createStream('Hello world');
$response = $psr17Factory->createResponse(200)->withBody($responseBody);
(new \Laminas\HttpHandlerRunner\Emitter\SapiEmitter())->emit($response);